--- @param extension Package
--- @param HY HY_Utility
--- @param U Utility
return function(extension, HY, U)
    local hy_kiruno = General:new(extension, "hy_kiruno", "jin_k", 4, 4, General.Female)
    ---@param originTable table
    ---@return table
    local function ToFreezeMark(originTable)
        local marks = {}
        for _, value in ipairs(originTable) do
            if value == "phase_judge" then
                table.insertIfNeed(marks, "freeze_judge")
            elseif value == "phase_draw" then
                table.insertIfNeed(marks, "freeze_draw")
            elseif value == "phase_play" then
                table.insertIfNeed(marks, "freeze_play")
            elseif value == "phase_discard" then
                table.insertIfNeed(marks, "freeze_discard")
            elseif value == tostring(fk.Damage) then
                table.insertIfNeed(marks, "freeze_damage")
            elseif value == tostring(fk.Damaged) then
                table.insertIfNeed(marks, "freeze_damaged")
            elseif value == tostring(fk.HpRecover) then
                table.insertIfNeed(marks, "freeze_recover")
            elseif value == tostring(fk.AfterCardsMove) then
                table.insertIfNeed(marks, "freeze_discard")
            end
        end
        return marks
    end
    local freeze = fk.CreateSkill {
        name = "freeze",
    }
    ---@param skill TriggerSkill
    ---@param event any
    ---@param target ServerPlayer
    ---@param player ServerPlayer
    ---@param data any
    local function FreezeFunc(skill, event, target, player, data)
        local room = player.room
        local skillTarget = room:getPlayerById(event:getCostData(skill)[1])
        local choices = { "phase_judge", "phase_draw", "phase_play", "phase_discard" }
        local valid = table.clone(choices)
        for _, phase in ipairs(player:getTableMark("freeze_selected")) do
            table.removeOne(valid, phase)
        end
        local result = room:askToChoice(player, {
            choices = valid,
            skill_name = freeze.name,
            prompt = "freeze_prompt_skip",
            all_choices = choices
        })

        local skips = skillTarget:getTableMark("freeze_skip")
        table.insertIfNeed(skips, result)
        room:setPlayerMark(skillTarget, "freeze_skip", skips)
        room:setPlayerMark(skillTarget, "@freeze_skip", ToFreezeMark(skips))

        local events = player:getTableMark("freeze-round")
        table.insertIfNeed(events, tostring(event))
        room:setPlayerMark(player, "freeze-round", events)
        room:setPlayerMark(player, "@freeze-round", ToFreezeMark(events))

        local selected = player:getTableMark("freeze_selected")
        table.insertIfNeed(selected, result)
        room:setPlayerMark(player, "freeze_selected", selected)

        if #selected == 4 then
            room:setPlayerMark(player, "freeze_selected", {})
            room:setPlayerMark(player, "freeze-round", {})
            room:setPlayerMark(player, "@freeze-round", 0)
        end
        local phases = { "phase_judge", "phase_draw", "phase_play", "phase_discard" }
        room:setPlayerMark(player, "@[:]freeze", table.except(phases, player:getTableMark("freeze_selected")))

        if not skillTarget.dead then
            room:drawCards(skillTarget, 1, freeze.name)
        end
    end
    freeze:addEffect(fk.GameStart, {
        can_refresh = function(self, event, target, player, data)
            return player:hasSkill(self, true, true)
        end,
        on_refresh = function(self, event, target, player, data)
            local room = player.room
            room:setPlayerMark(player, "@[:]freeze", { "phase_judge", "phase_draw", "phase_play", "phase_discard" })
        end,
    })
    freeze:addEffect(fk.Damage, {
        anim_type = "defensive",
        times = function(self, player)
            return #player:getTableMark("@[:]freeze")
        end,
        can_trigger = function(self, event, target, player, data)
            if not player:hasSkill(freeze.name) then
                return false
            end
            if target == player then
                return not table.contains(player:getTableMark("freeze-round"), tostring(event))
            end
        end,
        on_cost = function(self, event, target, player, data)
            local room = player.room
            event:setCostData(self, table.map(room:askToChoosePlayers(player, {
                targets = room.alive_players,
                min_num = 1,
                max_num = 1,
                prompt = "freeze_prompt",
                skill_name = freeze.name
            }), Util.IdMapper))
            return #event:getCostData(self) ~= 0
        end,
        on_use = function(self, event, target, player, data)
            FreezeFunc(self, event, target, player, data)
        end,
    })
    freeze:addEffect(fk.Damaged, {
        anim_type = "defensive",
        times = function(self, player)
            return #player:getTableMark("@[:]freeze")
        end,
        can_trigger = function(self, event, target, player, data)
            if not player:hasSkill(freeze.name) then
                return false
            end
            if target == player then
                return not table.contains(player:getTableMark("freeze-round"), tostring(event))
            end
        end,
        on_cost = function(self, event, target, player, data)
            local room = player.room
            event:setCostData(self, table.map(room:askToChoosePlayers(player, {
                targets = room.alive_players,
                min_num = 1,
                max_num = 1,
                prompt = "freeze_prompt",
                skill_name = freeze.name
            }), Util.IdMapper))
            return #event:getCostData(self) ~= 0
        end,
        on_use = function(self, event, target, player, data)
            FreezeFunc(self, event, target, player, data)
        end,
    })
    freeze:addEffect(fk.HpRecover, {
        anim_type = "defensive",
        times = function(self, player)
            return #player:getTableMark("@[:]freeze")
        end,
        can_trigger = function(self, event, target, player, data)
            if not player:hasSkill(freeze.name) then
                return false
            end
            if target == player then
                return not table.contains(player:getTableMark("freeze-round"), tostring(event))
            end
        end,
        on_cost = function(self, event, target, player, data)
            local room = player.room
            event:setCostData(self, table.map(room:askToChoosePlayers(player, {
                targets = room.alive_players,
                min_num = 1,
                max_num = 1,
                prompt = "freeze_prompt",
                skill_name = freeze.name
            }), Util.IdMapper))
            return #event:getCostData(self) ~= 0
        end,
        on_use = function(self, event, target, player, data)
            FreezeFunc(self, event, target, player, data)
        end,
    })
    freeze:addEffect(fk.AfterCardsMove, {
        anim_type = "defensive",
        times = function(self, player)
            return #player:getTableMark("@[:]freeze")
        end,
        can_trigger = function(self, event, target, player, data)
            if not player:hasSkill(freeze.name) then
                return false
            end
            return table.any(data, function(move)
                return move.from == player and move.moveReason == fk.ReasonDiscard and move.proposer and move.proposer == player and table.any(move.moveInfo, function(info)
                    return info.fromArea == Card.PlayerHand
                end)
            end) and not table.contains(player:getTableMark("freeze-round"), event)
        end,
        on_cost = function(self, event, target, player, data)
            local room = player.room
            event:setCostData(self, table.map(room:askToChoosePlayers(player, {
                targets = room.alive_players,
                min_num = 1,
                max_num = 1,
                prompt = "freeze_prompt",
                skill_name = freeze.name
            }), Util.IdMapper))
            return #event:getCostData(self) ~= 0
        end,
        on_use = function(self, event, target, player, data)
            FreezeFunc(self, event, target, player, data)
        end,
    })
    freeze:addEffect(fk.EventPhaseChanging, {
        can_trigger = function(self, event, target, player, data)
            switch(data.phase, {
                [Player.Judge] = function()
                    event:setCostData(self, "phase_judge")
                end,
                [Player.Draw] = function()
                    event:setCostData(self, "phase_draw")
                end,
                [Player.Play] = function()
                    event:setCostData(self, "phase_play")
                end,
                [Player.Discard] = function()
                    event:setCostData(self, "phase_discard")
                end,
            })
            return player:hasSkill(freeze.name) and table.contains(target:getTableMark("freeze_skip"), event:getCostData(self))
        end,
        on_cost = Util.TrueFunc,
        on_use = function(self, event, target, player, data)
            local room = player.room
            local skips = target:getTableMark("freeze_skip")
            table.removeOne(skips, event:getCostData(self))
            room:setPlayerMark(target, "freeze_skip", skips)
            if #skips == 0 then
                room:setPlayerMark(target, "@freeze_skip", 0)
            else
                room:setPlayerMark(target, "@freeze_skip", ToFreezeMark(skips))
            end
            target:skip(data.phase)
            data.skipped = true
        end,
    })
    extension:loadSkillSkels { freeze }
    hy_kiruno:addSkill("freeze")
    Fk:loadTranslationTable {
        ["hy_kiruno"] = "琪露诺",
        ["#hy_kiruno"] = "大愚若智",
        ["illustrator:hy_kiruno"] = "ゆうじん",
        ["designer:hy_kiruno"] = "黑曜人形",
        ["cv:hy_kiruno"] = "",

        ["freeze"] = "冰结",
        [":freeze"] = "每选项限一次且每轮每条件限一次，在你：1.造成伤害后；2.受到伤害后；3.回复体力后；4.弃置手牌后，你可以令一名角色摸一张牌并跳过其下个：1.判定阶段；2.摸牌阶段；3.出牌阶段；4.弃牌阶段。在你选择过全部选项后，重置“冰结”。",
        ["@[:]freeze"] = "冰结",
        ["@freeze_skip"] = "冰结",
        ["@freeze-round"] = "冰结",
        ["freeze_prompt"] = "冰结：你可以令一名角色摸一张牌并跳过一个阶段",
        ["freeze_prompt_skip"] = "冰结：选择跳过的阶段",
        ["freeze_judge"] = "判",
        ["freeze_draw"] = "摸",
        ["freeze_play"] = "出",
        ["freeze_discard"] = "弃",
        ["freeze_damage"] = "造",
        ["freeze_damaged"] = "受",
        ["freeze_recover"] = "回",
        [":phase_judge"] = "",
        [":phase_draw"] = "",
        [":phase_play"] = "",
        [":phase_discard"] = "",
    }
end
